home *** CD-ROM | disk | FTP | other *** search
/ Windows Game Programming for Dummies (2nd Edition) / WinGamProgFD.iso / pc / DirectX SDK / DXSDK / samples / Multimedia / DirectShow_WinXP / VMR / TxtPlayer / AllocPresenter.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-10-08  |  21.2 KB  |  763 lines

  1. //------------------------------------------------------------------------------
  2. // File: allocpresenter.cpp
  3. //
  4. // Desc: DirectShow sample code - Custom Allocator Presenter for VMR sample
  5. //
  6. // Copyright (c) 2000-2001 Microsoft Corporation.  All rights reserved.
  7. //------------------------------------------------------------------------------
  8.  
  9. #include <streams.h>
  10. #include <mmreg.h>
  11. #include "project.h"
  12. #include <stdarg.h>
  13. #include <stdio.h>
  14. #include <math.h>
  15.  
  16. #include "alloclib.h"
  17.  
  18.  
  19. /******************************Public*Routine******************************\
  20. * NonDelegatingQueryInterface
  21. *
  22. \**************************************************************************/
  23. STDMETHODIMP
  24. CMpegMovie::NonDelegatingQueryInterface(
  25.     REFIID riid,
  26.     void** ppv
  27.     )
  28. {
  29.     if(riid == IID_IVMRSurfaceAllocator)
  30.     {
  31.         return GetInterface((IVMRSurfaceAllocator*)this, ppv);
  32.     }
  33.     else if(riid == IID_IVMRImagePresenter)
  34.     {
  35.         return GetInterface((IVMRImagePresenter*)this, ppv);
  36.     }
  37.  
  38.     return CUnknown::NonDelegatingQueryInterface(riid,ppv);
  39. }
  40.  
  41.  
  42. //////////////////////////////////////////////////////////////////////////////
  43. //
  44. // IVMRSurfaceAllocator
  45. //
  46. //////////////////////////////////////////////////////////////////////////////
  47.  
  48. /******************************Public*Routine******************************\
  49. * AllocateSurfaces
  50. *
  51. \**************************************************************************/
  52. STDMETHODIMP
  53. CMpegMovie::AllocateSurface(
  54.     DWORD_PTR x,
  55.     VMRALLOCATIONINFO *w,
  56.     DWORD* lpdwBuffer,
  57.     LPDIRECTDRAWSURFACE7* lplpSurface
  58.     )
  59. {
  60.     DWORD dwFlags = w->dwFlags;
  61.     LPBITMAPINFOHEADER lpHdr = w->lpHdr;
  62.     LPDDPIXELFORMAT lpPixFmt = w->lpPixFmt;
  63.     LPSIZE lpAspectRatio = &w->szAspectRatio;
  64.     DWORD dwMinBuffers = w->dwMinBuffers;
  65.     DWORD dwMaxBuffers = w->dwMaxBuffers;
  66.  
  67.     if(!lpHdr)
  68.     {
  69.         return E_POINTER;
  70.     }
  71.  
  72.     if(!lpAspectRatio)
  73.     {
  74.         return E_POINTER;
  75.     }
  76.  
  77.     if(dwFlags & AMAP_PIXELFORMAT_VALID)
  78.     {
  79.         if(!lpPixFmt)
  80.         {
  81.             return E_INVALIDARG;
  82.         }
  83.     }
  84.  
  85.     HRESULT hr = AllocateSurfaceWorker(dwFlags, lpHdr, lpPixFmt,
  86.                                        lpAspectRatio,
  87.                                        dwMinBuffers, dwMaxBuffers,
  88.                                        lpdwBuffer, lplpSurface);
  89.     return hr;
  90. }
  91.  
  92. /******************************Public*Routine******************************\
  93. * AllocateSurfaceWorker
  94. *
  95. \**************************************************************************/
  96. HRESULT
  97. CMpegMovie::AllocateSurfaceWorker(
  98.     DWORD dwFlags,
  99.     LPBITMAPINFOHEADER lpHdr,
  100.     LPDDPIXELFORMAT lpPixFmt,
  101.     LPSIZE lpAspectRatio,
  102.     DWORD dwMinBuffers,
  103.     DWORD dwMaxBuffers,
  104.     DWORD* lpdwBuffer,
  105.     LPDIRECTDRAWSURFACE7* lplpSurface
  106.     )
  107. {
  108.     LPBITMAPINFOHEADER lpHeader = lpHdr;
  109.     if(!lpHeader)
  110.     {
  111.         DbgLog((LOG_ERROR, 1, TEXT("Can't get bitmapinfoheader from media type!!")));
  112.         return E_INVALIDARG;
  113.     }
  114.  
  115.     DDSURFACEDESC2 ddsd;
  116.     INITDDSTRUCT(ddsd);
  117.     ddsd.dwFlags = DDSD_CAPS|DDSD_HEIGHT|DDSD_WIDTH | DDSD_PIXELFORMAT;
  118.     ddsd.dwWidth = abs(lpHeader->biWidth);
  119.     ddsd.dwHeight = abs(lpHeader->biHeight);
  120.     ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY /*| DDSCAPS_TEXTURE */;
  121.  
  122.     ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  123.  
  124.     if(lpHdr->biCompression <= BI_BITFIELDS &&
  125.         m_DispInfo.bmiHeader.biBitCount <= lpHdr->biBitCount)
  126.     {
  127.         ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  128.  
  129.         if(lpHdr->biBitCount == 32)
  130.         {
  131.             ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
  132.             ddsd.ddpfPixelFormat.dwRBitMask = 0xff0000;
  133.             ddsd.ddpfPixelFormat.dwGBitMask = 0xff00;
  134.             ddsd.ddpfPixelFormat.dwBBitMask = 0xff;
  135.         }
  136.         else if(lpHdr->biBitCount == 16)
  137.         {
  138.             ddsd.ddpfPixelFormat.dwRGBBitCount = 16;
  139.             ddsd.ddpfPixelFormat.dwRBitMask = 0xF800;
  140.             ddsd.ddpfPixelFormat.dwGBitMask = 0x07e0;
  141.             ddsd.ddpfPixelFormat.dwBBitMask = 0x001F;
  142.         }
  143.     }
  144.     else if(lpHdr->biCompression > BI_BITFIELDS)
  145.     {
  146.         const DWORD dwCaps = (DDCAPS_BLTFOURCC | DDCAPS_BLTSTRETCH);
  147.         if((dwCaps & m_ddHWCaps.dwCaps) != dwCaps)
  148.         {
  149.             DbgLog((LOG_ERROR, 1,
  150.                 TEXT("Can't BLT_FOURCC | BLT_STRETCH!!")));
  151.             return E_FAIL;
  152.         }
  153.         ddsd.ddpfPixelFormat.dwFourCC = lpHdr->biCompression;
  154.         ddsd.ddpfPixelFormat.dwFlags = DDPF_FOURCC;
  155.         ddsd.ddpfPixelFormat.dwYUVBitCount = lpHdr->biBitCount;
  156.     }
  157.     else
  158.     {
  159.         return E_FAIL;
  160.     }
  161.  
  162.  
  163.     // Adjust width and height, if the driver requires it
  164.     DWORD dwWidth  = ddsd.dwWidth;
  165.     DWORD dwHeight = ddsd.dwHeight;
  166.  
  167.     HRESULT hr = m_lpDDObj->CreateSurface(&ddsd, &m_lpDDTexture, NULL);
  168.  
  169.     if(SUCCEEDED(hr))
  170.     {
  171.         m_VideoAR = *lpAspectRatio;
  172.  
  173.         m_VideoSize.cx = abs(lpHeader->biWidth);
  174.         m_VideoSize.cy = abs(lpHeader->biHeight);
  175.  
  176.         SetRect(&m_rcDst, 0, 0, m_VideoSize.cx, m_VideoSize.cy);
  177.         m_rcSrc = m_rcDst;
  178.  
  179.         hr = PaintDDrawSurfaceBlack(m_lpDDTexture);
  180.  
  181.         *lplpSurface = m_lpDDTexture;
  182.         *lpdwBuffer = 1;
  183.     }
  184.  
  185.     return hr;
  186. }
  187.  
  188.  
  189. /******************************Public*Routine******************************\
  190. * FreeSurfaces()
  191. *
  192. \**************************************************************************/
  193. STDMETHODIMP
  194. CMpegMovie::FreeSurface(DWORD_PTR w)
  195. {
  196.     if(m_lpDDTexture)
  197.     {
  198.         m_lpDDTexture->Release();
  199.         m_lpDDTexture = NULL;
  200.     }
  201.  
  202.     return S_OK;
  203. }
  204.  
  205.  
  206. /******************************Public*Routine******************************\
  207. * PrepareSurface
  208. *
  209. \**************************************************************************/
  210. STDMETHODIMP
  211. CMpegMovie::PrepareSurface(
  212.     DWORD_PTR w,
  213.     LPDIRECTDRAWSURFACE7 lplpSurface,
  214.     DWORD dwSurfaceFlags
  215.     )
  216. {
  217.     return S_OK;
  218. }
  219.  
  220. /******************************Public*Routine******************************\
  221. * AdviseNotify
  222. *
  223. \**************************************************************************/
  224. STDMETHODIMP
  225. CMpegMovie::AdviseNotify(
  226.     IVMRSurfaceAllocatorNotify* lpIVMRSurfAllocNotify
  227.     )
  228. {
  229.     return E_NOTIMPL;
  230. }
  231.  
  232.  
  233. //////////////////////////////////////////////////////////////////////////////
  234. //
  235. // IVMRImagePresenter
  236. //
  237. //////////////////////////////////////////////////////////////////////////////
  238.  
  239. /******************************Public*Routine******************************\
  240. * StartPresenting()
  241. *
  242. \**************************************************************************/
  243. STDMETHODIMP
  244. CMpegMovie::StartPresenting(DWORD_PTR w)
  245. {
  246.     return S_OK;
  247. }
  248.  
  249. /******************************Public*Routine******************************\
  250. * StopPresenting()
  251. *
  252. \**************************************************************************/
  253. STDMETHODIMP
  254. CMpegMovie::StopPresenting(DWORD_PTR w)
  255. {
  256.     return S_OK;
  257. }
  258.  
  259. /******************************Public*Routine******************************\
  260. * PresentImage
  261. *
  262. \**************************************************************************/
  263. STDMETHODIMP
  264. CMpegMovie::PresentImage(
  265.     DWORD_PTR w,
  266.     VMRPRESENTATIONINFO* p
  267.     )
  268. {
  269.     //
  270.     // Call the app specific function to render the scene
  271.     //
  272.     LPDIRECTDRAWSURFACE7 lpSurface = p->lpSurf;
  273.     const REFERENCE_TIME rtNow = p->rtStart;
  274.     const DWORD dwSurfaceFlags = p->dwFlags;
  275.  
  276.     CAutoLock Lock(&m_AppImageLock);
  277.  
  278.     RECT rSrc = {0, 0, m_VideoSize.cx, m_VideoSize.cy};
  279.     RECT rDst = {0, 0, WIDTH(&m_rcDst), HEIGHT(&m_rcDst)};
  280.  
  281.     //PaintDDrawSurfaceBlack(m_lpBackBuffer);
  282.     //m_lpBltAlpha->AlphaBlt(&rDst, m_lpDDTexture, &rSrc, 0xFF);
  283.     m_lpBackBuffer->Blt(&rDst, m_lpDDTexture, &rSrc, DDBLT_WAIT, NULL);
  284.  
  285.     rDst.left   = m_cxFontImg;
  286.     rDst.top    = m_cyFontImg * 1;
  287.     rDst.right  = rDst.left + (m_cxFontImg * 40);
  288.     rDst.bottom = rDst.top  + (m_cyFontImg * 4);
  289.  
  290.     rSrc.left   = 0;
  291.     rSrc.top    = 0;
  292.     rSrc.right  = (m_cxFontImg * 40);
  293.     rSrc.bottom = (m_cyFontImg * 4);
  294.     m_lpBltAlpha->AlphaBlt(&rDst, m_lpDDAppImage, &rSrc, 0x80);
  295.  
  296.  
  297.     RECT rc = m_rcDst;
  298.     RECT rcSrc;
  299.  
  300.     SetRect(&rcSrc, 0, 0, WIDTH(&rc), HEIGHT(&rc));
  301.     m_lpPriSurf->Blt(&rc, m_lpBackBuffer, &rcSrc, DDBLT_WAIT, NULL);
  302.  
  303.     return S_OK;
  304. }
  305.  
  306.  
  307. //////////////////////////////////////////////////////////////////////////////
  308. //
  309. // Allocator Presenter helper functions
  310. //
  311. //////////////////////////////////////////////////////////////////////////////
  312.  
  313.  
  314. /*****************************Private*Routine******************************\
  315. * InitDisplayInfo
  316. *
  317. \**************************************************************************/
  318. BOOL
  319. InitDisplayInfo(
  320.     AMDISPLAYINFO* lpDispInfo
  321.     )
  322. {
  323.     static char szDisplay[] = "DISPLAY";
  324.     ZeroMemory(lpDispInfo, sizeof(*lpDispInfo));
  325.  
  326.     HDC hdcDisplay = CreateDCA(szDisplay, NULL, NULL, NULL);
  327.     HBITMAP hbm = CreateCompatibleBitmap(hdcDisplay, 1, 1);
  328.  
  329.     lpDispInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
  330.     GetDIBits(hdcDisplay, hbm, 0, 1, NULL, (BITMAPINFO *)lpDispInfo, DIB_RGB_COLORS);
  331.     GetDIBits(hdcDisplay, hbm, 0, 1, NULL, (BITMAPINFO *)lpDispInfo, DIB_RGB_COLORS);
  332.  
  333.     DeleteObject(hbm);
  334.     DeleteDC(hdcDisplay);
  335.  
  336.     return TRUE;
  337. }
  338.  
  339. /*****************************Private*Routine******************************\
  340. * DDARGB32SurfaceInit
  341. *
  342. \**************************************************************************/
  343. HRESULT
  344. CMpegMovie::DDARGB32SurfaceInit(
  345.     LPDIRECTDRAWSURFACE7* lplpDDS,
  346.     BOOL bTexture,
  347.     DWORD cx,
  348.     DWORD cy
  349.     )
  350. {
  351.     DDSURFACEDESC2 ddsd;
  352.     HRESULT hRet;
  353.  
  354.     *lplpDDS = NULL;
  355.  
  356.     INITDDSTRUCT(ddsd);
  357.  
  358.     ddsd.ddpfPixelFormat.dwSize = sizeof(DDPIXELFORMAT);
  359.     ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
  360.     if(bTexture)
  361.     {
  362.         ddsd.ddpfPixelFormat.dwFlags |= DDPF_ALPHAPIXELS;
  363.     }
  364.     ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
  365.     if(bTexture)
  366.     {
  367.         ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xFF000000;
  368.     }
  369.     ddsd.ddpfPixelFormat.dwRBitMask        = 0x00FF0000;
  370.     ddsd.ddpfPixelFormat.dwGBitMask        = 0x0000FF00;
  371.     ddsd.ddpfPixelFormat.dwBBitMask        = 0x000000FF;
  372.  
  373.  
  374.     if(bTexture)
  375.     {
  376.         ddsd.ddsCaps.dwCaps =  DDSCAPS_TEXTURE;
  377.         ddsd.ddsCaps.dwCaps2 = (DDSCAPS2_TEXTUREMANAGE | DDSCAPS2_HINTDYNAMIC);
  378.     }
  379.     else
  380.     {
  381.         ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_OFFSCREENPLAIN;
  382.     }
  383.     ddsd.dwFlags = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS | DDSD_PIXELFORMAT;
  384.     ddsd.dwBackBufferCount = 0;
  385.  
  386.     if(bTexture)
  387.     {
  388.         for(ddsd.dwWidth=1;  cx>ddsd.dwWidth;   ddsd.dwWidth<<=1);
  389.         for(ddsd.dwHeight=1; cy>ddsd.dwHeight; ddsd.dwHeight<<=1);
  390.     }
  391.     else
  392.     {
  393.         ddsd.dwWidth=cx;
  394.         ddsd.dwHeight=cy;
  395.     }
  396.  
  397.  
  398.     // Attempt to create the surface with theses settings
  399.     hRet = m_lpDDObj->CreateSurface(&ddsd, lplpDDS, NULL);
  400.  
  401.     return hRet;
  402. }
  403.  
  404.  
  405. /*****************************Private*Routine******************************\
  406. * CreateFontCache
  407. *
  408. \**************************************************************************/
  409. HRESULT
  410. CMpegMovie::CreateFontCache(
  411.     int cyFont
  412.     )
  413. {
  414.     //
  415.     // Initialize the LOGFONT structure - we want to
  416.     // create an "anti-aliased" Lucida Consol font
  417.     //
  418.     LOGFONT lfChar;
  419.     ZeroMemory(&lfChar, sizeof(lfChar));
  420.     lfChar.lfHeight = -cyFont;
  421.     lfChar.lfCharSet = OEM_CHARSET ;
  422.     lfChar.lfPitchAndFamily = FIXED_PITCH | FF_MODERN ;
  423.     lstrcpy(lfChar.lfFaceName, TEXT("Lucida Console")) ;
  424.     lfChar.lfWeight = FW_NORMAL ;
  425.     lfChar.lfOutPrecision = OUT_STRING_PRECIS ;
  426.     lfChar.lfClipPrecision = CLIP_STROKE_PRECIS ;
  427.     lfChar.lfQuality = ANTIALIASED_QUALITY;
  428.  
  429.  
  430.     HFONT hFont = CreateFontIndirect(&lfChar) ;
  431.     if(!hFont)
  432.     {
  433.         return E_OUTOFMEMORY;
  434.     }
  435.  
  436.     //
  437.     // The following magic is necessary to get GDI to rasterize
  438.     // the font with anti-aliasing switched on when we later use
  439.     // the font in a DDraw Surface.  The doc's say that this is only
  440.     // necessary in Win9X - but Win2K seems to require it too.
  441.     //
  442.     SIZE size;
  443.     HDC hdcWin = GetDC(NULL);
  444.     hFont = (HFONT)SelectObject(hdcWin, hFont);
  445.     GetTextExtentPoint32(hdcWin, TEXT("A"), 1, &size);
  446.     hFont = (HFONT)SelectObject(hdcWin, hFont);
  447.     ReleaseDC(NULL, hdcWin);
  448.  
  449.     //
  450.     // Make sure that the font doesn't get too big.
  451.     //
  452.     if(size.cx * GRID_CX > 1024)
  453.     {
  454.         return S_OK;
  455.     }
  456.  
  457.  
  458.     //
  459.     // Delete the old font and assign the new one
  460.     //
  461.     RELEASE(m_lpDDSFontCache);
  462.     if(m_hFont)
  463.     {
  464.         DeleteObject(m_hFont);
  465.     }
  466.     m_cxFont = size.cx; m_cyFont = size.cy;
  467.     m_hFont = hFont;
  468.  
  469.  
  470.     //
  471.     // Create the DDraw ARGB32 surface that we will use
  472.     // for the font cache.
  473.     //
  474.  
  475.     HRESULT hr = DDARGB32SurfaceInit(&m_lpDDSFontCache, TRUE, 16 * size.cx, 6 * size.cy);
  476.     if(hr == DD_OK)
  477.     {
  478.  
  479.         HDC hdcDest;
  480.  
  481.         m_lpDDSFontCache->GetDC(&hdcDest);
  482.  
  483.         //
  484.         // Select the font into the DDraw surface and draw the characters
  485.         //
  486.         m_hFont = (HFONT)SelectObject(hdcDest, m_hFont);
  487.         SetTextColor(hdcDest, RGB(255,255,255));
  488.         SetBkColor(hdcDest, RGB(0,0,0));
  489.         SetBkMode(hdcDest, OPAQUE);
  490.  
  491.         int row, col; TCHAR ch = (TCHAR)32;
  492.         for(row = 0; row < 6; row++)
  493.         {
  494.             for(col = 0; col < 16; col++)
  495.             {
  496.                 TextOut(hdcDest, col * size.cx, row * size.cy, &ch, 1);
  497.                 ch++;
  498.             }
  499.         }
  500.         m_hFont = (HFONT)SelectObject(hdcDest, m_hFont);
  501.         m_lpDDSFontCache->ReleaseDC(hdcDest);
  502.  
  503.         DDSURFACEDESC2 surfDesc;
  504.         INITDDSTRUCT(surfDesc);
  505.         HRESULT hr = m_lpDDSFontCache->Lock(NULL, &surfDesc, DDLOCK_WAIT, NULL);
  506.         if(hr == DD_OK)
  507.         {
  508.  
  509.             LPDWORD lpDst = (LPDWORD)surfDesc.lpSurface;
  510.             for(row = 0; row < 6 * size.cy; row++)
  511.             {
  512.  
  513.                 LPDWORD lp = lpDst;
  514.                 for(col = 0; col < 16 * size.cx; col++)
  515.                 {
  516.  
  517.                     DWORD dwPel = *lp;
  518.                     if(dwPel)
  519.                     {
  520.                         dwPel <<= 24;
  521.                         dwPel |= 0x00FFFFFF;
  522.                     }
  523.                     else
  524.                     {
  525.                         dwPel = 0x80000000;
  526.                     }
  527.  
  528.                     *lp++ = dwPel;
  529.                 }
  530.                 lpDst += (surfDesc.lPitch / 4);
  531.             }
  532.             m_lpDDSFontCache->Unlock(NULL);
  533.         }
  534.     }
  535.  
  536.     return S_OK;
  537. }
  538.  
  539.  
  540. /*****************************Private*Routine******************************\
  541. * Initialize3DEnvironment
  542. *
  543. \**************************************************************************/
  544. HRESULT
  545. CMpegMovie::Initialize3DEnvironment(
  546.     HWND hWnd
  547.     )
  548. {
  549.     HRESULT hr;
  550.  
  551.     //
  552.     // Create the IDirectDraw interface. The first parameter is the GUID,
  553.     // which is allowed to be NULL. If there are more than one DirectDraw
  554.     // drivers on the system, a NULL guid requests the primary driver. For
  555.     // non-GDI hardware cards like the 3DFX and PowerVR, the guid would need
  556.     // to be explicity specified . (Note: these guids are normally obtained
  557.     // from enumeration, which is convered in a subsequent tutorial.)
  558.     //
  559.  
  560.     m_hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY);
  561.  
  562.     hr = DirectDrawCreateEx(NULL, (VOID**)&m_lpDDObj, IID_IDirectDraw7, NULL);
  563.     if(FAILED(hr))
  564.         return hr;
  565.  
  566.     //
  567.     // get the h/w caps for this device
  568.     //
  569.     INITDDSTRUCT(m_ddHWCaps);
  570.     hr = m_lpDDObj->GetCaps(&m_ddHWCaps, NULL);
  571.     if(FAILED(hr))
  572.         return hr;
  573.     InitDisplayInfo(&m_DispInfo);
  574.  
  575.     //
  576.     // Set the Windows cooperative level. This is where we tell the system
  577.     // whether we will be rendering in fullscreen mode or in a window. Note
  578.     // that some hardware (non-GDI) may not be able to render into a window.
  579.     // The flag DDSCL_NORMAL specifies windowed mode. Using fullscreen mode
  580.     // is the topic of a subsequent tutorial. The DDSCL_FPUSETUP flag is a
  581.     // hint to DirectX to optomize floating points calculations. See the docs
  582.     // for more info on this. Note: this call could fail if another application
  583.     // already controls a fullscreen, exclusive mode.
  584.     //
  585.     hr = m_lpDDObj->SetCooperativeLevel(hWnd, DDSCL_NORMAL);
  586.     if(FAILED(hr))
  587.         return hr;
  588.  
  589.     //
  590.     // Initialize a surface description structure for the primary surface. The
  591.     // primary surface represents the entire display, with dimensions and a
  592.     // pixel format of the display. Therefore, none of that information needs
  593.     // to be specified in order to create the primary surface.
  594.     //
  595.     DDSURFACEDESC2 ddsd;
  596.     ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
  597.     ddsd.dwSize = sizeof(DDSURFACEDESC2);
  598.     ddsd.dwFlags        = DDSD_CAPS;
  599.     ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
  600.  
  601.     //
  602.     // Create the primary surface.
  603.     //
  604.     hr = m_lpDDObj->CreateSurface(&ddsd, &m_lpPriSurf, NULL);
  605.     if(FAILED(hr))
  606.         return hr;
  607.  
  608.     //
  609.     // Create a clipper object which handles all our clipping for cases when
  610.     // our window is partially obscured by other windows. This is not needed
  611.     // for apps running in fullscreen mode.
  612.     //
  613.     LPDIRECTDRAWCLIPPER pcClipper;
  614.     hr = m_lpDDObj->CreateClipper(0, &pcClipper, NULL);
  615.     if(FAILED(hr))
  616.         return hr;
  617.  
  618.     //
  619.     // Associate the clipper with our window. Note that, afterwards, the
  620.     // clipper is internally referenced by the primary surface, so it is safe
  621.     // to release our local reference to it.
  622.     //
  623.     pcClipper->SetHWnd(0, hWnd);
  624.     m_lpPriSurf->SetClipper(pcClipper);
  625.     pcClipper->Release();
  626.  
  627.     //
  628.     // Before creating the device, check that we are NOT in a palettized
  629.     // display. That case will cause CreateDevice() to fail, since this simple
  630.     // tutorial does not bother with palettes.
  631.     //
  632.     ddsd.dwSize = sizeof(DDSURFACEDESC2);
  633.     m_lpDDObj->GetDisplayMode(&ddsd);
  634.     if(ddsd.ddpfPixelFormat.dwRGBBitCount <= 8)
  635.         return DDERR_INVALIDMODE;
  636.  
  637.     DWORD dwRenderWidth  = ddsd.dwWidth;
  638.     DWORD dwRenderHeight = ddsd.dwHeight;
  639.  
  640.  
  641.     //
  642.     // Setup a surface description to create a backbuffer. This is an
  643.     // offscreen plain surface with dimensions equal to the current display
  644.     // size.
  645.  
  646.     // The DDSCAPS_3DDEVICE is needed so we can later query this surface
  647.     // for an IDirect3DDevice interface.
  648.     //
  649.     ZeroMemory(&ddsd, sizeof(DDSURFACEDESC2));
  650.     ddsd.dwSize = sizeof(DDSURFACEDESC2);
  651.     ddsd.dwFlags        = DDSD_WIDTH | DDSD_HEIGHT | DDSD_CAPS;
  652.     ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY | DDSCAPS_3DDEVICE;
  653.     ddsd.dwWidth = dwRenderWidth;
  654.     ddsd.dwHeight = dwRenderHeight;
  655.  
  656.  
  657.     //
  658.     // Create the backbuffer. The most likely reason for failure is running
  659.     // out of video memory. (A more sophisticated app should handle this.)
  660.     //
  661.     hr = m_lpDDObj->CreateSurface(&ddsd, &m_lpBackBuffer, NULL);
  662.     if(FAILED(hr))
  663.         return hr;
  664.  
  665.     //
  666.     // Create the textbuffer.
  667.     //
  668.     // The text buffer should be RGB32 (for now - later I'll try
  669.     // ARGB16:4:4:4:4, but that is a lot more work).
  670.     //
  671.     hr = DDARGB32SurfaceInit(&m_lpDDAppImage, TRUE,
  672.         1024, MulDiv(4, (int)dwRenderHeight, GRID_CY));
  673.     if(FAILED(hr))
  674.         return hr;
  675.  
  676.     PaintDDrawSurfaceBlack(m_lpDDAppImage);
  677.  
  678.  
  679.     //
  680.     // Create the device. The device is created off of our back buffer, which
  681.     // becomes the render target for the newly created device. Note that the
  682.     // z-buffer must be created BEFORE the device
  683.     //
  684.     m_lpBltAlpha = new CAlphaBlt(m_lpBackBuffer, &hr);
  685.     if(m_lpBltAlpha == NULL || hr != DD_OK)
  686.     {
  687.         if(m_lpBltAlpha == NULL)
  688.         {
  689.             hr = E_OUTOFMEMORY;
  690.         }
  691.         delete m_lpBltAlpha;
  692.     }
  693.  
  694.     hr = CreateFontCache(32);
  695.  
  696.     return hr;
  697. }
  698.  
  699.  
  700. POINT LookUpChar(char ch, int cxFont, int cyFont)
  701. {
  702.     ch -= 32;
  703.  
  704.     int row = ch / 16;
  705.     int col = ch % 16;
  706.  
  707.     POINT pt;
  708.  
  709.     pt.x = col * cxFont;
  710.     pt.y = row * cyFont;
  711.  
  712.     return pt;
  713. }
  714.  
  715.  
  716. /******************************Public*Routine******************************\
  717. * SetAppText
  718. *
  719. \**************************************************************************/
  720. BOOL
  721. CMpegMovie::SetAppText(
  722.     char* sz
  723.     )
  724. {
  725.     DDBLTFX ddFX;
  726.     INITDDSTRUCT(ddFX);
  727.     ddFX.dwFillColor =  0xFF80FF80;
  728.     CAutoLock Lock(&m_AppImageLock);
  729.     m_lpDDAppImage->Blt(NULL, NULL, NULL, DDBLT_COLORFILL, &ddFX);
  730.  
  731.     m_cxFontImg = m_cxFont;
  732.     m_cyFontImg = m_cyFont;
  733.     RECT rcDst = {0, 0, m_cxFont, m_cyFont};
  734.  
  735.     while(*sz)
  736.     {
  737.         if(*sz == '\n')
  738.         {
  739.             OffsetRect(&rcDst, 0, m_cyFont);
  740.             rcDst.left = 0;
  741.             rcDst.right = m_cxFont;
  742.         }
  743.         else
  744.         {
  745.             POINT pt = LookUpChar(*sz, m_cxFont, m_cyFont);
  746.  
  747.             RECT rcSrc;
  748.             rcSrc.left = pt.x;
  749.             rcSrc.top  = pt.y;
  750.             rcSrc.right = pt.x + m_cxFont;
  751.             rcSrc.bottom  = pt.y + m_cyFont;
  752.  
  753.             m_lpDDAppImage->Blt(&rcDst, m_lpDDSFontCache, &rcSrc, DDBLT_WAIT, NULL);
  754.             OffsetRect(&rcDst, m_cxFont, 0);
  755.         }
  756.         sz++;
  757.     }
  758.  
  759.     return TRUE;
  760. }
  761.  
  762.  
  763.